package com.chuangjiangx.member.basic.ddd.application;

import com.chuangjiangx.commons.exception.BaseException;
import com.chuangjiangx.member.basic.dao.model.InMbrConfig;
import com.chuangjiangx.member.basic.dao.model.InMbrConfigExample;
import com.chuangjiangx.member.basic.ddd.domain.model.*;
import com.chuangjiangx.member.coupon.dao.mapper.InMbrHasCouponMapper;
import com.chuangjiangx.member.coupon.dao.model.InMbrCoupon;
import com.chuangjiangx.member.coupon.dao.model.InMbrHasCouponExample;
import com.chuangjiangx.member.score.dao.mapper.InMbrScoreStreamMapper;
import com.chuangjiangx.member.basic.dao.mapper.InMbrConfigMapper;
import com.chuangjiangx.member.coupon.dao.mapper.InMbrCouponMapper;
import com.chuangjiangx.member.coupon.ddd.domain.model.MbrHasCoupon;
import com.chuangjiangx.member.coupon.ddd.domain.service.CouponDomainService;
import com.chuangjiangx.member.basic.ddd.domain.service.MemberMsgDomainService;
import com.chuangjiangx.member.basic.ddd.domain.service.MemberDomainService;
import com.chuangjiangx.member.basic.ddd.domain.service.MemberScoreService;

import com.chuangjiangx.member.basic.ddd.application.command.RegisterMemberCommand;
import com.chuangjiangx.member.basic.ddd.domain.service.model.MemberLogin;
import com.chuangjiangx.member.score.dao.model.InMbrScoreStreamExample;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreStream;
import com.chuangjiangx.member.score.ddd.domain.repository.MbrScoreStreamRepository;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreType;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * @author cj-ch
 * @date 2018/3/19 下午3:55
 */
@Service
public class LoginApplication {


    @Autowired
    private MemberRepository memberRepository;
    @Autowired
    private MbrUserMappingRepository mbrUserMappingRepository;
    @Autowired
    private MbrAccountRepository mbrAccountRepository;
    @Autowired
    private MemberScoreService memberScoreService;
    @Autowired
    private MemberApplication memberApplication;
    @Autowired
    private MemberDomainService memberDomainService;
    @Autowired
    private CouponDomainService couponDomainService;
    @Autowired
    private InMbrConfigMapper inMbrConfigMapper;
    @Autowired
    private InMbrCouponMapper inMbrCouponMapper;
    @Autowired
    private InMbrHasCouponMapper inMbrHasCouponMapper;
    @Autowired
    private InMbrScoreStreamMapper inMbrScoreStreamMapper;
    @Autowired
    private MbrScoreStreamRepository mbrScoreStreamRepository;
    @Autowired
    private MemberMsgDomainService memberMsgDomainService;

    /**
     * 微信端手动登录
     * 手机号+商户Id
     * 服务商公众号openid和商户公众号openid要么一起没有,要么一起有
     * @param userContext
     * @return
     */
    public MemberLogin wxLogin(MbrUserContext userContext){
        Validate.notNull(userContext.getMobile());
        Validate.notNull(userContext.getMerchantId());
        Validate.notNull(userContext.getMbrUserMappingType());
        Validate.notNull(userContext.getOpenId());
//        Validate.notNull(userContext.getMopenId());
        Validate.notNull(userContext.getState());
//        Validate.notNull(userContext.getHeadimgurl());
        String mobile = userContext.getMobile();
        MerchantId merchantId = new MerchantId(userContext.getMerchantId());
        Member member = memberRepository.fromMerchantIdAndMobile(merchantId, mobile);
        switch (userContext.getState()){
            case PAYMENT_IS:
                //支付即会员-根据openid能查询到会员信息,但是没有绑定手机号码
                //
                MbrUserMapping userMapping = mbrUserMappingRepository.from(userContext.getOpenId(), merchantId, MbrUserMappingType.WX);
                if(null == userMapping){
                    throw new BaseException("","当前会员非支付即会员");
                }
                Member masterMember = memberRepository.fromId(userMapping.getMemberId());
                if(null == masterMember){
                    throw new BaseException("","支付即会员的信息不存在");
                }
                if(StringUtils.isNotBlank(masterMember.getMobile())){
                    //支付即会员没有手机号
                    throw new BaseException("","当前会员非支付即会员");
                }
                //登录手机号码是否已经注册会员
                if(null != member ){
                    //已经注册
                    //判断是否有绑定信息
                    MbrUserMapping mobileUserMapping = mbrUserMappingRepository.from(member.getId(), merchantId, MbrUserMappingType.WX);
                    if(null == mobileUserMapping){
                        //合并,绑定手机号码,清除多余会员记录,发送注册信息
                        /*
                        场景描述:
                        1.客户通过客户端使用手机号码注册会员
                        2.客户通过支付成为支付即会员
                        1和2都进行过就会产生两个会员记录需要合并
                        1-member表有记录
                        2-member\mbr_user_mapping\其他表都可能有记录,所以由1合并到2
                         */
                        //将通过openid注册的会员的积分信息转移并且删除,
                        //转移
                        memberDomainService.merge(masterMember,member);
                    }else{
                        //判断是否是同一个会员
                        if(!Objects.equals(masterMember.getId().getId(),member.getId().getId())){
                            //异常!手机号码已经被注册
                            throw new BaseException("","手机号码已经被注册");
                        }
                    }
                }
                //绑定手机号码
                masterMember.modifyMobile(mobile);
                memberRepository.update(masterMember);
                member = masterMember;
                break;
            case NON_MEMBERS:
                //非会员-根据openid不能查询到会员信息
                if(null == member){
                    //注册会员
                    RegisterMemberCommand registerMemberCommand = new RegisterMemberCommand(
                            userContext.getName(),
                            userContext.getSex(),
                            mobile,
                            userContext.getHeadimgurl(),
                            null,
                            userContext.getMerchantId(),
                            null,null,
                            MbrSourceTerminal.H5_TERMINAL.value,
                            "",null,
                            userContext.getOpenId(),
                            userContext.getMopenId(),""
                    );
                    member = memberApplication.wxAutoRegisterMember(registerMemberCommand, MbrUserMappingType.WX);
                } else {
                    //绑定openid和mopenid
                    //判断是否已经有了绑定信息
                    MbrUserMapping mobileUserMapping = mbrUserMappingRepository.from(member.getId(), merchantId, userContext.getMbrUserMappingType());
                    if(mobileUserMapping == null){
                        mobileUserMapping = new MbrUserMapping(
                                member.getId(),
                                merchantId,
                                userContext.getOpenId(),
                                userContext.getMopenId(),
                                userContext.getMbrUserMappingType(),"",""
                        );
                    } else {
                        mobileUserMapping.modifyOpenid(userContext.getOpenId());
                        mobileUserMapping.modifyMopenid(userContext.getMopenId());
                    }
                    memberDomainService.bindWX(member,mobileUserMapping);
                }
                break;
            case MEMBER:

                break;
            default:
                break;
        }


        MemberLogin memberLogin = new MemberLogin();
        InMbrConfigExample example = new InMbrConfigExample();
        example.createCriteria()
                .andMerchantIdEqualTo(userContext.getMerchantId());
        List<InMbrConfig> inMbrConfigs = inMbrConfigMapper.selectByExample(example);
        if (!inMbrConfigs.isEmpty()){
            //开卡赠送卡券
            Long giftMbrCouponId = inMbrConfigs.get(0).getGiftMbrCouponId();
            if (giftMbrCouponId !=null) {
                InMbrCoupon inMbrCoupon = inMbrCouponMapper.selectByPrimaryKey(giftMbrCouponId);
                if (inMbrCoupon != null) {
                    //查询是否已经赠送过
                    InMbrHasCouponExample inMbrHasCouponExample = new InMbrHasCouponExample();
                    inMbrHasCouponExample.createCriteria()
                            .andMemberIdEqualTo(member.getId().getId())
                            .andMbrCouponIdEqualTo(giftMbrCouponId);
                    long count = inMbrHasCouponMapper.countByExample(inMbrHasCouponExample);
                    if(count < 1){
                        //没有赠送过,则赠送
                        MbrHasCoupon mbrHasCoupon = couponDomainService.memberClaimCoupon(member.getId(), inMbrCoupon.getCouponNumber());
                        memberLogin.setMbrHasCouponId(mbrHasCoupon.getId().getId());
                    }
                }
            }
            //开卡赠送积分
            if (inMbrConfigs.get(0).getGiftScore()!=null&&!inMbrConfigs.get(0).getGiftScore().equals(new BigDecimal(0))){
                // 查询是否赠送过积分
                InMbrScoreStreamExample inMbrScoreStreamExample = new InMbrScoreStreamExample();
                inMbrScoreStreamExample.createCriteria()
                        .andMemberIdEqualTo(member.getId().getId())
                        .andTypeEqualTo(MbrScoreType.CARD_GIFT.value);
                long count = inMbrScoreStreamMapper.countByExample(inMbrScoreStreamExample);
                if(count < 1){
                    Long score = inMbrConfigs.get(0).getGiftScore().longValue();
                    String remark = "开通会员卡赠送"+score+"积分";
                    MbrAccount mbrAccount = mbrAccountRepository.fromMemberId(member.getId());
                    mbrAccount.changeScore(score, MbrScoreType.CARD_GIFT);
                    mbrAccountRepository.update(mbrAccount);
                    MbrScoreStream mbrScoreStream = new MbrScoreStream(
                            member.getId(),
                            score,
                            MbrScoreType.CARD_GIFT,
                            null,
                            null,
                            null,
                            null,
                            mbrAccount.getAvailableScore(),
                            remark,
                            null,
                            null,
                            null,
                            null
                    );
                    mbrScoreStreamRepository.save(mbrScoreStream);
                    memberMsgDomainService.sendMbrScoreChangeMsg(userContext.getMerchantId(), mbrAccount, mbrScoreStream,
                            remark);
                }
            }
        }

        memberLogin.setMember(member);
        // 设置微信映射关系,判断是否需要重定向获取商户公众号Openid----后面优化
        MbrUserMapping mobileUserMapping = mbrUserMappingRepository.from(member.getId(), merchantId, MbrUserMappingType.WX);
        memberLogin.setMbrUserMapping(mobileUserMapping);
        return memberLogin;
    }



    public Member wxAppletRegister(MbrUserContext userContext) {
        RegisterMemberCommand registerMemberCommand = new RegisterMemberCommand(
                userContext.getName(),
                userContext.getSex(),
                userContext.getMobile(),
                userContext.getHeadimgurl(),
                null,
                userContext.getMerchantId(),
                null,null,
                MbrSourceTerminal.APPLET_TERMINAL.value,
                "",userContext.getMerchantUserId(),
                "",
                "",userContext.getSubOpenId()
        );
        Member member = memberApplication.wxAutoRegisterMember(registerMemberCommand, MbrUserMappingType.WX);
        return member;
    }

    public void bindWXUserMapping(Member member, MbrUserMapping userMapping) {
        memberDomainService.bindWX(member,userMapping);
    }
    public void bindWXUserMapping(Long memberId, MbrUserMapping userMapping) {
        Member member = memberRepository.fromId(new MemberId(memberId));
        memberDomainService.bindWX(member,userMapping);
    }


    /**
     * 人脸入了成功后
     * 更新FaceId,faceImg
     */
    public void entryFaceSuccess(Long memberId,Long merchantId,String imageUrl,String faceId){
        inputFaceImgUrlUserMapping(memberId,merchantId,imageUrl);
        Member member = memberRepository.fromId(new MemberId(memberId));
        member.modifyFaceId(faceId);
        memberRepository.update(member);
    }
    /**
     * 人脸采集成功后，记录user_mapping表
     */
    public void inputFaceImgUrlUserMapping(Long memberId,Long merchantId,String imageUrl) {
        MbrUserMapping mbrUserMapping = mbrUserMappingRepository.from(
                new MemberId(memberId),
                new MerchantId(merchantId),
                MbrUserMappingType.WX
        );
        Assert.notNull(mbrUserMapping,"mbrUserMapping is null");
        mbrUserMapping.modifyAiFaceImg(imageUrl);
        Member member = memberRepository.fromId(new MemberId(memberId));
        bindWXUserMapping(member,mbrUserMapping);
    }



}
